using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Hermes.Framework;
using Hermes.Framework.FileSystem;
using Hermes.Framework.Implementation.File;

namespace Hermes.Framework.Implementation.Directory
{
    /// <summary>
    /// Copy a directory.
    /// </summary>
    public class TxDirectoryCopy : TxOperationTemplate, ITransactableCopy
    {
        /// <summary>
        /// Default constructor, with source and objective location assigned.
        /// </summary>
        /// <param name="srcFileName">The source location.</param>
        /// <param name="dstFileName">The objective location.</param>
        public TxDirectoryCopy(string srcFileName, string dstFileName)
            : base(srcFileName, dstFileName)
        {

        }

        /// <summary>
        /// Execute the copy.
        /// </summary>
        public void Copy()
        {
            base.Execute(this.srcFileName, this.dstFileName);
        }

        /// <summary>
        /// Called by the Copy() method to actually do the operation.
        /// </summary>
        protected override void Operate()
        {
            this.Copy(this.srcFileName, this.dstFileName);
        }

        /// <summary>
        /// A recursive routine to perform the operation.
        /// </summary>
        /// <param name="srcDirectoryName">The source directory location.</param>
        /// <param name="dstDirectoryName">The objective directory location.</param>
        protected void Copy(string srcDirectoryName, string dstDirectoryName)
        {
            if (!this.fileSystem.IsDirectory(dstDirectoryName))
            {
                TxDirectoryCreate create = new TxDirectoryCreate(dstDirectoryName);
                create.ResourceManager = this.resourceManager;
                create.FileSystem = this.fileSystem;

                create.Create();
            }

            for(int index = 0; index < this.fileSystem.GetItemCount(srcDirectoryName); index++)
            {
                string item = this.fileSystem.GetItem(srcDirectoryName, index);
                string srcFullName = MergeFileName(srcDirectoryName, item);
                string dstFullName = MergeFileName(dstDirectoryName, item);

                if (this.fileSystem.Exists(srcFullName))
                {
                    TxFileCopy copy = new TxFileCopy(srcFullName, dstFullName);
                    copy.ResourceManager = this.resourceManager;
                    copy.FileSystem = this.fileSystem;

                    copy.Copy();
                }
                else
                {
                    this.Copy(srcFullName, dstFullName);
                }
            }
        }

        private static string MergeFileName(string srcDirectoryName, string item)
        {
            if (srcDirectoryName.EndsWith("\\") || srcDirectoryName.EndsWith("/"))
            {
                return srcDirectoryName + item;
            }
            return srcDirectoryName + "\\" + item;
        }

        /// <summary>
        /// Default implementation and does nothing here, commit job are delegated by directory create and file copy.
        /// </summary>
        public override void Commit()
        {
            // does nothing...
        }
        
        /// <summary>
        /// Default implementation and does nothing here, rollback are delegated by directory create and file copy.
        /// </summary>
        public override void Rollback()
        {
            // does nothing...
        }
    }
}
